package com.github.rxyor.carp.spring.boot.eventbus.core;

import java.io.Serializable;
import java.util.UUID;
import lombok.Data;
import lombok.Getter;
import lombok.ToString;

/**
 *<p>
 *
 *</p>
 *
 * @author liuyang
 * @date 2020/4/11 周六 21:48:00
 * @since 1.0.0
 */
@Data
public class DelayEvent implements Serializable {

    private static final long serialVersionUID = -3578671637632577601L;
    private IEvent origin;

    private Long expireTime;

    public DelayEvent() {
    }

    public DelayEvent(IEvent origin) {
        this.origin = origin;
    }

    public String getEventKey() {
        return origin != null ? origin.getEventKey() : UUID.randomUUID().toString();
    }

    public int computeDelayLevel() {
        if (expireTime == null || expireTime <= System.currentTimeMillis()) {
            return DelayLevel.L0.level;
        }
        //代码执行可能有延迟，因此先/1000忽略mills
        final long delay = expireTime / 1000 - System.currentTimeMillis() / 1000;

        int lastLevel = DelayLevel.L0.level;
        for (DelayLevel dl : DelayLevel.values()) {
            if (dl.delay > delay) {
                break;
            }
            lastLevel = dl.level;
        }
        return lastLevel;
    }

    public long delay() {
        if (expireTime == null || expireTime <= System.currentTimeMillis()) {
            return 0L;
        }
        return (expireTime - System.currentTimeMillis()) / 1000;
    }

    @ToString
    public enum DelayLevel {
        L0(0, 0),
        L1(1, 1),
        L2(2, 5),
        L3(3, 10),
        L4(4, 30),
        L5(5, 60),
        L6(6, 120),
        L7(7, 180),
        L8(8, 240),
        L9(9, 300),
        L10(10, 360),
        L11(11, 420),
        L12(12, 480),
        L13(13, 540),
        L14(14, 600),
        L15(15, 1200),
        L16(16, 1800),
        L17(17, 3600),
        L18(18, 7200),
        ;

        @Getter
        private final int level;

        @Getter
        private final int delay;

        DelayLevel(int level, int delay) {
            this.level = level;
            this.delay = delay;
        }
    }
}
